home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / dsp / a56_10sh.z / a56_10sh / a56.y < prev    next >
Text File  |  1996-06-25  |  31KB  |  1,474 lines

  1. %{
  2. /*******************************************************
  3.  *
  4.  *  a56 - a DSP56001 assembler
  5.  *
  6.  *  Written by Quinn C. Jensen
  7.  *  July 1990
  8.  *  jensenq@npd.novell.com (or jensenq@qcj.icon.com)
  9.  *
  10.  *******************************************************\
  11.  
  12. /*
  13.  * Copyright (C) 1990, 1991 Quinn C. Jensen
  14.  *
  15.  * Permission to use, copy, modify, distribute, and sell this software
  16.  * and its documentation for any purpose is hereby granted without fee,
  17.  * provided that the above copyright notice appear in all copies and
  18.  * that both that copyright notice and this permission notice appear
  19.  * in supporting documentation.  The author makes no representations
  20.  * about the suitability of this software for any purpose.  It is
  21.  * provided "as is" without express or implied warranty.
  22.  *
  23.  */
  24.  
  25. /*
  26.  *  a56.y - The YACC grammar for the assembler.
  27.  *
  28.  *  Note:  This module requires a "BIG" version of YACC.  I had to
  29.  *  recompile YACC in the largest mode available.
  30.  *
  31.  */
  32.  
  33. #include "a56.h"
  34. unsigned int w0, w1, pc;
  35. extern BOOL list_on;
  36. BOOL uses_w1;
  37. int just_rep = 0;
  38. extern char inline[];
  39. char *spaces(), *luntab();
  40. char segs[] = "PXYL";
  41. int seg;
  42. int substatement = 0;
  43.  
  44. #define R_R6            0x0001
  45. #define R_R5            0x0002
  46. #define R_R4            0x0004
  47. #define R_DATA_ALU_ACCUM    0x0008
  48. #define R_CTL_REG        0x0010
  49. #define R_FUNKY_CTL_REG        0x0020
  50. #define R_SDX            0x0040
  51. #define R_SDY            0x0080
  52. #define R_LSD            0x0100
  53. #define R_AB            0x0200
  54. #define R_XREG            0x0400
  55. #define R_YREG            0x0800
  56. %}
  57.  
  58. %union {
  59.     int ival;    /* integer value */
  60.     char *sval;    /* string */
  61.     int cval;    /* character */
  62.     char cond;    /* condition */
  63.     struct regs {
  64.         int r6, r5, r4, data_alu_accum, ctl_reg, funky_ctl_reg;
  65.         int sdx, sdy, lsd, ab, xreg, yreg;
  66.         int flags;
  67.     } regs;
  68.     struct ea {
  69.         int mode;
  70.         int ext;
  71.         int pp;
  72.     } ea;
  73. }
  74.  
  75. %token <ival> CHEX CDEC FRAC AREG BREG MREG NREG RREG XREG YREG
  76. %token <ival> OP OPA OPP
  77. %token <cond> OP_JCC OP_JSCC OP_TCC
  78. %token <sval> SYM
  79. %token <sval> STRING
  80. %token <cval> CHAR
  81. %token COMMENT
  82. %token XMEM
  83. %token YMEM
  84. %token LMEM
  85. %token PMEM
  86. %token AAAA
  87. %token A10
  88. %token BBBB
  89. %token B10
  90. %token AABB
  91. %token BBAA
  92. %token XXXX
  93. %token YYYY
  94. %token SR
  95. %token MR
  96. %token CCR
  97. %token OMR
  98. %token SP
  99. %token SSH
  100. %token SSL
  101. %token LA
  102. %token LC
  103. %token EOL
  104. %token EOS
  105.  
  106. %token OP_ABS
  107. %token OP_ADC
  108. %token OP_ADD
  109. %token OP_ADDL
  110. %token OP_ADDR
  111. %token OP_ASL
  112. %token OP_ASR
  113. %token OP_CLR
  114. %token OP_CMP
  115. %token OP_CMPM
  116. %token OP_DIV
  117. %token OP_MAC
  118. %token OP_MACR
  119. %token OP_MPY
  120. %token OP_MPYR
  121. %token OP_NEG
  122. %token OP_NORM
  123. %token OP_RND
  124. %token OP_SBC
  125. %token OP_SUB
  126. %token OP_SUBL
  127. %token OP_SUBR
  128. %token OP_TFR
  129. %token OP_TST
  130. %token OP_AND
  131. %token OP_ANDI
  132. %token OP_EOR
  133. %token OP_LSL
  134. %token OP_LSR
  135. %token OP_NOT
  136. %token OP_OR
  137. %token OP_ORI
  138. %token OP_ROL
  139. %token OP_ROR
  140. %token OP_BCLR
  141. %token OP_BSET
  142. %token OP_BCHG
  143. %token OP_BTST
  144. %token OP_DO
  145. %token OP_ENDDO
  146. %token OP_LUA
  147. %token OP_MOVE
  148. %token OP_MOVEC
  149. %token OP_MOVEM
  150. %token OP_MOVEP
  151. %token OP_ILLEGAL
  152. %token OP_INCLUDE
  153. %token OP_JMP
  154. %token OP_JCLR
  155. %token OP_JSET
  156. %token OP_JSR
  157. %token OP_JSCLR
  158. %token OP_JSSET
  159. %token OP_NOP
  160. %token OP_REP
  161. %token OP_RESET
  162. %token OP_RTI
  163. %token OP_RTS
  164. %token OP_STOP
  165. %token OP_SWI
  166. %token OP_WAIT
  167. %token OP_EQU
  168. %token OP_ORG
  169. %token OP_DC
  170. %token OP_END
  171. %token OP_PAGE
  172. %token OP_PSECT
  173. %token SHL
  174. %token SHR
  175.  
  176. %type <ival> num num_or_sym abs_addr abs_short_addr io_short_addr 
  177. %type <ival> num_or_sym_expr
  178. %type <ival> a_b x_or_y ea b5_10111_max
  179. %type <ival> p6_ean_a6 ea_no_ext p6_ea_a6 ea_a6 ea_a12
  180. %type <ival> ea_no_ext 
  181. %type <ival> ea_short
  182. %type <ival> prog_ctl_reg
  183. %type <ival> ix ix_long
  184. %type <ival> op8_1 op8_2 op8_3 op8_4 op8_5 op8_6 op8_7 op8_8
  185. %type <ival> mpy_arg mpy_srcs plus_minus
  186. %type <ival> sd3
  187. %type <ival> funky_ctl_reg tcc_sd space
  188. %type <regs> regs
  189. %type <ea> movep_ea_pp
  190.  
  191. %type <ival> expr
  192. %left '|'
  193. %left '^'
  194. %left SHL SHR
  195. %left '&'
  196. %left '+' '-'
  197. %left '*' '/' '%'
  198. %right '~'
  199.  
  200. %start input
  201.  
  202. %%
  203.  
  204. /*%%%********************* top syntax ***********************/
  205.  
  206. input    :    /* empty */
  207.     |    input statement
  208.     ;
  209.  
  210. statement
  211.     :    good_stuff EOL
  212.             {substatement = 0;
  213.             if(NOT check_psect(seg, pc) && pass == 2)
  214.                 yyerror("psect violation");
  215.             }
  216.     |    good_stuff EOS
  217.             {substatement++;
  218.             if(NOT check_psect(seg, pc) && pass == 2)
  219.                 yyerror("psect violation");
  220.             }
  221.     |    error
  222.     ;
  223.  
  224. good_stuff
  225.     :    /* empty */
  226.             {if(pass == 2 && list_on) {
  227.                 printf("\n");
  228.             }}
  229.     |    COMMENT
  230.             {if(pass == 2 && NOT substatement && list_on) {
  231.                 printf("%s%s\n", spaces(0), luntab(inline));
  232.             }}
  233.     |    assembler_ops comment_field
  234.     |    label_field operation_field comment_field
  235.             {char *printcode();
  236.             if(pass == 2) {
  237.                 gencode(seg, pc, w0);
  238.                 if(list_on) printf("%c:%04X %s %s\n", segs[seg], pc, 
  239.                     printcode(w0), substatement ? "" :
  240.                         luntab(inline));
  241.                 pc++;
  242.                 if(uses_w1) {
  243.                     gencode(seg, pc, w1);
  244.                     if(list_on) printf("%c:%04X %s\n", segs[seg], pc,
  245.                                printcode(w1 & 0xFFFFFF));
  246.                     pc++;
  247.                 }
  248.             } else {
  249.                 pc++;
  250.                 if(uses_w1)
  251.                     pc++;
  252.             }
  253.             w0 = w1 = 0; uses_w1 = FALSE;}
  254.     |    SYM comment_field
  255.             {sym_def($1, pc);
  256.             free($1);
  257.             if(pass == 2) {
  258.                 if(list_on) printf("%c:%04X%s%s\n", segs[seg], pc, 
  259.                     spaces(14-8), substatement ? "" :
  260.                         luntab(inline));
  261.             }}
  262.     ;
  263.  
  264. assembler_ops
  265.     :    SYM OP_EQU expr
  266.             {sym_def($1, $3);
  267.             free($1);
  268.             if(pass == 2) {
  269.                 if(list_on) printf("%06X%s%s\n", $3 & 0xFFFFFF, 
  270.                     spaces(14-6-2), 
  271.                     substatement ? "" : luntab(inline));
  272.             }}
  273.     |    OP_PSECT SYM
  274.             {struct psect *pp = find_psect($2);
  275.             if(NOT pp) {
  276.                 if(pass == 2)
  277.                     yyerror("undefined psect");
  278.             } else {
  279.                 seg = pp->seg;
  280.                 pc = pp->pc;
  281.                 set_psect(pp);
  282.                 if(pass == 2) {
  283.                     if(list_on) printf("%c:%04X%s%s\n", 
  284.                         segs[seg], pc, 
  285.                         spaces(14-8), substatement ? "" : luntab(inline));
  286.                 }
  287.             }
  288.             free($2);}
  289.     |    OP_PSECT SYM space expr ':' expr
  290.             {new_psect($2, $3, $4, $6);
  291.             if(pass == 2) {
  292.                 if(list_on) printf("%c:%04X %04X%s%s\n", 
  293.                     segs[$3], $4, $6, spaces(14-8+4+1), 
  294.                     substatement ? "" : luntab(inline));
  295.             }}
  296.     |    OP_ORG space expr
  297.             {pc = $3;
  298.             seg = $2;
  299.             if(pass == 2) {
  300.                 if(list_on) printf("%c:%04X%s%s\n", segs[seg], pc, 
  301.                     spaces(14-8), substatement ? "" : luntab(inline));
  302.             }}
  303.     |    OP_ORG space expr ',' space expr
  304.             {pc = $3;
  305.             seg = $2;
  306.             if(pass == 2) {
  307.                 if(list_on) printf("%c:%04X%s%s\n", segs[seg], pc, 
  308.                     spaces(14-8), substatement ? "" : luntab(inline));
  309.             }}
  310.     |    label_field OP_DC dc_list
  311.     |    OP_PAGE num ',' num ',' num ',' num
  312.             {if(pass == 2 && NOT substatement && list_on) {
  313.                 printf("%s%s\n", spaces(0), luntab(inline));
  314.             }}
  315.     |    OP_INCLUDE STRING
  316.             {if(pass == 2 && NOT substatement && list_on) {
  317.                 printf("%s%s\n", spaces(0), luntab(inline));
  318.             }
  319.             include($2); /* free($2); */
  320.             }
  321.     |    OP_END
  322.             {if(pass == 2 && NOT substatement && list_on) {
  323.                 printf("%s%s\n", spaces(0), luntab(inline));
  324.             }}
  325.     ;
  326.  
  327. dc_list
  328.     :    dc_list ',' dc_stuff
  329.     |    dc_stuff
  330.     ;
  331.  
  332. dc_stuff
  333.     :    STRING
  334.             {int len = strlen($1), i; char *cp; w0 = 0;
  335.             if(len % 3 == 2)
  336.                 len++;    /* force empty word */
  337.             for(i = 0, cp = $1; i < len; i++, cp++) {
  338.                 w0 |= (*cp & 0xFF) << (2 - (i % 3)) * 8;
  339.                 if(i % 3 == 2 || i == len - 1) {
  340.                     if(pass == 2) {
  341.                         if(list_on) printf("%c:%04X %06X%s%s\n",
  342.                             segs[seg], pc, w0, 
  343.                             spaces(14-6+5), 
  344.                             substatement ? "" : luntab(inline));
  345.                         gencode(seg, pc, w0);
  346.                         substatement++;
  347.                     }
  348.                     pc++; w0 = 0;
  349.                 }
  350.             }
  351.             free($1);}
  352.      |    expr
  353.             {if(pass == 2) {
  354.                 if(list_on) printf("%c:%04X %06X%s%s\n", 
  355.                     segs[seg], pc,
  356.                     $1 & 0xFFFFFF, spaces(14-6+5),
  357.                     substatement ? "" : luntab(inline));
  358.                 gencode(seg, pc, $1);
  359.                 substatement++;
  360.             }
  361.             pc++;}
  362.  
  363. space    :    PMEM
  364.             {$$ = PROG;}
  365.     |    XMEM
  366.             {$$ = XDATA;}
  367.     |    YMEM
  368.             {$$ = YDATA;}
  369.     |    LMEM
  370.             {$$ = LDATA;}
  371.     ;       
  372.  
  373. label_field
  374.     :    SYM
  375.             {sym_def($1, pc);
  376.             free($1);}
  377.     |    /* empty */
  378.     ;
  379.  
  380. operation_field
  381.     :    operation
  382.             {if(just_rep) 
  383.                 just_rep--;}
  384.     ;
  385.  
  386. comment_field
  387.     :    COMMENT
  388.     |    /* empty */
  389.     ;
  390.  
  391. operation
  392.     :    no_parallel
  393.     |    parallel_ok
  394.             {w0 |= 0x200000;}
  395.     |    parallel_ok parallel_move
  396.     ;
  397.  
  398. /*%%%************* instructions that allow parallel moves ****************/
  399.  
  400. parallel_ok
  401.     :
  402.         OP_MPY mpy_arg
  403.             {w0 |= 0x80 | $2 << 2;}
  404.     |    OP_MPYR mpy_arg
  405.             {w0 |= 0x81 | $2 << 2;}
  406.     |    OP_MAC mpy_arg
  407.             {w0 |= 0x82 | $2 << 2;}
  408.     |    OP_MACR mpy_arg
  409.             {w0 |= 0x83 | $2 << 2;}
  410.  
  411.     |       OP_SUB op8_1
  412.             {w0 |= 0x04 | $2 << 3;}
  413.     |    OP_ADD op8_1
  414.             {w0 |= 0x00 | $2 << 3;}
  415.     |    OP_MOVE
  416.             {w0 |= 0x00;}
  417.  
  418.     |    OP_TFR op8_2
  419.             {w0 |= 0x01 | $2 << 3;}
  420.     |    OP_CMP op8_2
  421.             {w0 |= 0x05 | $2 << 3;}
  422.     |    OP_CMPM op8_2
  423.             {w0 |= 0x07 | $2 << 3;}
  424.  
  425.     |    OP_RND op8_3
  426.             {w0 |= 0x11 | $2 << 3;}
  427.     |    OP_ADDL op8_3
  428.             {w0 |= 0x12 | $2 << 3;}
  429.     |    OP_CLR op8_3
  430.             {w0 |= 0x13 | $2 << 3;}
  431.     |    OP_SUBL op8_3
  432.             {w0 |= 0x16 | $2 << 3;}
  433.     |    OP_NOT op8_3
  434.             {w0 |= 0x17 | $2 << 3;}
  435.  
  436.     |    OP_ADDR op8_4
  437.             {w0 |= 0x02 | $2 << 3;}
  438.     |    OP_TST op8_4
  439.             {w0 |= 0x03 | $2 << 3;}
  440.     |    OP_SUBR op8_4
  441.             {w0 |= 0x06 | $2 << 3;}
  442.  
  443.     |       OP_AND op8_5
  444.             {w0 |= 0x46 | $2 << 3;}
  445.     |    OP_OR op8_5
  446.             {w0 |= 0x42 | $2 << 3;}
  447.     |       OP_EOR op8_5
  448.             {w0 |= 0x43 | $2 << 3;}
  449.  
  450.     |       OP_ASR op8_6
  451.             {w0 |= 0x22 | $2 << 3;}
  452.     |       OP_LSR op8_6
  453.             {w0 |= 0x23 | $2 << 3;}
  454.     |       OP_ABS op8_6
  455.             {w0 |= 0x26 | $2 << 3;}
  456.     |       OP_ROR op8_6
  457.             {w0 |= 0x27 | $2 << 3;}
  458.  
  459.     |       OP_ASL op8_7
  460.             {w0 |= 0x32 | $2 << 3;}
  461.     |       OP_LSL op8_7
  462.             {w0 |= 0x33 | $2 << 3;}
  463.     |       OP_NEG op8_7
  464.             {w0 |= 0x36 | $2 << 3;}
  465.     |       OP_ROL op8_7
  466.             {w0 |= 0x37 | $2 << 3;}
  467.  
  468.     |       OP_ADC op8_8
  469.             {w0 |= 0x21 | $2 << 3;}
  470.     |       OP_SBC op8_8
  471.             {w0 |= 0x25 | $2 << 3;}
  472.     ;
  473.  
  474. mpy_arg    :    plus_minus mpy_srcs ',' a_b
  475.             {$$ = $1 | $4 << 1 | $2 << 2;}
  476.     ;
  477.  
  478. plus_minus
  479.     :    '+'    
  480.             {$$ = 0;}
  481.     |    '-'    
  482.             {$$ = 1;}
  483.     |    
  484.             {$$ = 0;}
  485.     ;
  486.  
  487. mpy_srcs
  488.     :       XREG ',' XREG
  489.             {switch ($1 << 4 | $3) {
  490.                 case 0x00: $$ = 0x0; break;
  491.                 case 0x01: 
  492.                 case 0x10: $$ = 0x2; break;
  493.                 case 0x11: 
  494.                     yyerror("illegal source operands"); 
  495.                     break;
  496.             }}                  
  497.     |    YREG ',' YREG
  498.             {switch ($1 << 4 | $3) {
  499.                 case 0x00: $$ = 0x1; break;
  500.                 case 0x01: 
  501.                 case 0x10: $$ = 0x3; break;
  502.                 case 0x11: 
  503.                     yyerror("illegal source operands"); 
  504.                     break;
  505.             }}                  
  506.     |    XREG ',' YREG
  507.             {switch ($1 << 4 | $3) {
  508.                 case 0x00: $$ = 0x5; break;
  509.                 case 0x01: $$ = 0x4; break;
  510.                 case 0x10: $$ = 0x6; break;
  511.                 case 0x11: $$ = 0x7; break;
  512.             }}                  
  513.     |    YREG ',' XREG
  514.             {switch ($1 << 4 | $3) {
  515.                 case 0x00: $$ = 0x5; break;
  516.                 case 0x01: $$ = 0x6; break;
  517.                 case 0x10: $$ = 0x4; break;
  518.                 case 0x11: $$ = 0x7; break;
  519.             }}                  
  520.     ;
  521.  
  522. op8_1    :    BBBB ',' AAAA
  523.             {$$ = 0x2;}
  524.     |    AAAA ',' BBBB
  525.             {$$ = 0x3;}
  526.     |    XXXX ',' a_b
  527.             {$$ = 0x4 | $3;}
  528.     |    YYYY ',' a_b
  529.             {$$ = 0x6 | $3;}
  530.     |    XREG ',' a_b
  531.             {$$ = 0x8 | $1 << 2 | $3;}
  532.     |    YREG ',' a_b
  533.             {$$ = 0xA | $1 << 2 | $3;}
  534.     ;
  535.  
  536. op8_2    :    BBBB ',' AAAA
  537.             {$$ = 0x2;}
  538.     |    AAAA ',' BBBB
  539.             {$$ = 0x3;}
  540.     |    XREG ',' a_b
  541.             {$$ = 0x8 | $1 << 2 | $3;}
  542.     |    YREG ',' a_b
  543.             {$$ = 0xA | $1 << 2 | $3;}
  544.     ;
  545.  
  546. op8_3    :    AAAA
  547.             {$$ = 0x0;}
  548.     |    BBBB
  549.             {$$ = 0x1;}
  550.     |    BBBB ',' AAAA
  551.             {$$ = 0x0;}
  552.     |    AAAA ',' BBBB
  553.             {$$ = 0x1;}
  554.     ;
  555.  
  556. op8_4    :    op8_3
  557.             {$$ = $1;}
  558.     ;
  559.  
  560. op8_5    :    XREG ',' a_b
  561.             {$$ = 0x0 | $1 << 2 | $3;}
  562.     |    YREG ',' a_b
  563.             {$$ = 0x2 | $1 << 2 | $3;}
  564.     ;
  565.  
  566. op8_6    :    a_b
  567.             {$$ = $1;}
  568.     ;
  569.  
  570. op8_7    :    a_b
  571.             {$$ = $1;}
  572.     ;
  573.  
  574. op8_8    :    XXXX ',' a_b
  575.             {$$ = 0x0 | $3;}
  576.     |    YYYY ',' a_b
  577.             {$$ = 0x2 | $3;}
  578.     ;
  579.  
  580. a_b    :    AAAA
  581.             {$$ = 0;}
  582.     |    BBBB
  583.             {$$ = 1;}
  584.     ;
  585.  
  586. no_parallel
  587.     :    control_inst
  588.             {if(just_rep == 1)
  589.                 yyerror("instruction not allowed after REP");}
  590.     |    bit_inst
  591.     |    move_inst
  592.     |    arith_inst
  593.     ;
  594.  
  595. /*%%%************** non-parallel arithmetic and logical ********************/
  596.  
  597. arith_inst
  598.     :    OP_NORM RREG ',' a_b
  599.             {w0 |= 0x01D815 | $2 << 8 | $4 << 3;}
  600.     |    OP_DIV sd3
  601.             {w0 |= 0x018040 | $2 << 3;}
  602.     |    or_op ix ',' funky_ctl_reg
  603.             {w0 |= 0x0000F8 | ($2 & 0xFF) << 8 | $4;}
  604.     |    and_op ix ',' funky_ctl_reg
  605.             {w0 |= 0x0000B8 | ($2 & 0xFF) << 8 | $4;}
  606.     ;
  607.  
  608. or_op    :    OP_OR
  609.     |    OP_ORI
  610.     ;
  611.  
  612. and_op    :    OP_AND
  613.     |    OP_ANDI
  614.     ;
  615.  
  616. /*%%%******************************* control instructions **********************/
  617.  
  618. control_inst
  619.     :    OP_JSCC ea_a12
  620.             {if($2) {
  621.                 w0 |= 0x0BC0A0 | $1 << 0;
  622.             } else {
  623.                 w0 |= 0x0F0000 | $1 << 12;
  624.             }}
  625.     |    OP_JCC ea_a12
  626.             {if($2) {
  627.                 w0 |= 0x0AC0A0 | $1 << 0;
  628.             } else {
  629.                 w0 |= 0x0E0000 | $1 << 12;
  630.             }}
  631.     |    OP_JSR ea_a12
  632.             {if($2) {
  633.                 w0 |= 0x0BC080;
  634.             } else {
  635.                 w0 |= 0x0D0000;
  636.             }}
  637.     |    OP_JMP ea_a12
  638.             {if($2) {
  639.                 w0 |= 0x0AC080;
  640.             } else {
  641.                 w0 |= 0x0C0000;
  642.             }}
  643.  
  644.     |    OP_JSSET control_args
  645.             {w0 |= 0x0B0020;}
  646.     |    OP_JSCLR control_args
  647.             {w0 |= 0x0B0000;}
  648.     |    OP_JSET control_args
  649.             {w0 |= 0x0A0020;}
  650.     |    OP_JCLR control_args
  651.             {w0 |= 0x0A0000;}
  652.  
  653.     |    OP_REP rep_args
  654.             {just_rep = 2;}
  655.     |    OP_DO do_args
  656.             {uses_w1++;}
  657.     |    OP_ENDDO
  658.             {w0 |= 0x00008C;}
  659.     |    OP_STOP
  660.             {w0 |= 0x000087;}
  661.     |    OP_WAIT
  662.             {w0 |= 0x000086;}
  663.     |    OP_RESET
  664.             {w0 |= 0x000084;}
  665.     |    OP_RTS
  666.             {w0 |= 0x00000C;}
  667.     |    OP_SWI
  668.             {w0 |= 0x000006;}
  669.     |    OP_ILLEGAL
  670.             {w0 |= 0x000005;}
  671.     |    OP_RTI
  672.             {w0 |= 0x000004;}
  673.     |    OP_NOP
  674.             {w0 |= 0x000000;
  675.             just_rep = 0;}
  676.     ;
  677.  
  678. do_args    :    ix ',' abs_addr
  679.             {w0 |= 0x060080 | ($1 & 0xFF) << 8 | ($1 & 0xF00)>> 8;
  680.             if($1 > 0xFFF && pass == 2) {
  681.                 yyerror("warning: immediate operand truncated");
  682.             }
  683.             w1 |= $3-1;}
  684.     |    regs ',' abs_addr
  685.             {w0 |= 0x06C000 | $1.r6 << 8;
  686.             w1 |= $3-1;}
  687.     |    x_or_y ea_no_ext ',' abs_addr
  688.             {w0 |= 0x064000 | $2 << 8 | $1 << 6;
  689.             w1 |= $4-1;}
  690.     |    x_or_y abs_short_addr ',' abs_addr    /* allow forced */
  691.             {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
  692.             if($2 > 0x003F && pass == 2)
  693.                 yyerror("warning: address operand truncated");
  694.             w1 |= $4-1;}
  695.     |    x_or_y abs_addr ',' abs_addr
  696.             {w0 |= 0x060000 | ($2 & 0x3F) << 8 | $1 << 6;
  697.             if($2 > 0x003F && pass == 2)
  698.                 yyerror("warning: address operand truncated");
  699.             w1 |= $4-1;}
  700.     ;               
  701.  
  702. rep_args
  703.     :    ix
  704.             {w0 |= 0x0600A0 | ($1 & 0xFF) << 8 | ($1 & 0xF00)>> 8;
  705.             if($1 > 0xFFF && pass == 2) {
  706.                 yyerror("warning: immediate operand truncated");
  707.             }}
  708.     |    regs
  709.             {w0 |= 0x06C020 | $1.r6 << 8;}
  710.     |    x_or_y ea_no_ext
  711.             {w0 |= 0x064020 | $1 << 6 | $2 << 8;}
  712.     |    x_or_y abs_addr
  713.             {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
  714.             if($2 > 0x003F && pass == 2)
  715.                 yyerror("warning: address operand truncated");
  716.             }
  717.     |    x_or_y abs_short_addr    /* forced */
  718.             {w0 |= 0x060020 | $1 << 6 | ($2 & 0x3F) << 8;
  719.             if($2 > 0x003F && pass == 2)
  720.                 yyerror("warning: address operand truncated");
  721.             }
  722.     ;
  723.  
  724. control_args
  725.     :    b5_10111_max ',' x_or_y p6_ean_a6 ',' abs_addr
  726.             {w0 |= $1 << 0 | $3 << 6;
  727.             uses_w1++;
  728.             w1 = $6;}
  729.     |    b5_10111_max ',' regs ',' abs_addr
  730.             {w0 |= 0x00C000 | $1 << 0 | $3.r6 << 8;
  731.             uses_w1++;
  732.             w1 = $5;}
  733.  
  734. p6_ean_a6
  735.     :    abs_addr    /* in pass 2 can always discern size. */
  736.                 /* Sometimes in pass one, too.  But since */
  737.                 /* address extension is always used for the */
  738.                 /* branch target, pass 1 can assume the */
  739.                 /* symbol value will fit; warning in pass 2 */
  740.                 /* if it doesn't */
  741.             {if($1 != -1) {    /* symbol defined */
  742.                 w0 |= ($1 & 0x3F) << 8;
  743.                 if($1 >= 0xFFC0) {
  744.                     w0 |= 0x008080;
  745.                 } else {
  746.                     w0 |= 0x000080;
  747.                     if($1 > 0x003F && pass == 2)
  748.                         yyerror("warning: address operand truncated");
  749.                 }
  750.             }}
  751.     |    abs_short_addr
  752.             {if($1 != -1) {
  753.                 if($1 > 0x3F && pass == 2)
  754.                     yyerror("warning: address operand truncated");
  755.                 w0 |= 0x000080 | ($1 & 0x3F) << 8;
  756.             }}
  757.     |    io_short_addr
  758.             {if($1 != -1) {
  759.                 if($1 < 0xFFC0 && pass == 2)
  760.                     yyerror("warning: address operand truncated");
  761.                 w0 |= 0x008080 | ($1 & 0x3F) << 8;
  762.             }}
  763.     |    ea_no_ext
  764.             {w0 |= 0x004080 | $1 << 8;}
  765.     ;
  766.  
  767. /*%%%**************************** bit instructions ***************************/
  768.  
  769. bit_inst
  770.     :    OP_BTST bit_args
  771.             {w0 |= 0x0B0020;}
  772.     |    OP_BCHG bit_args
  773.             {w0 |= 0x0B0000;}
  774.     |    OP_BSET bit_args
  775.             {w0 |= 0x0A0020;}
  776.     |    OP_BCLR bit_args
  777.             {w0 |= 0x0A0000;}
  778.     ;               
  779.  
  780. bit_args
  781.     :    b5_10111_max ',' x_or_y p6_ea_a6
  782.             {w0 |= $1 << 0 | $3 << 6;}
  783.     |    b5_10111_max ',' regs
  784.             {w0 |= 0x00C040 | $1 << 0 | $3.r6 << 8;}
  785.     ;           
  786.  
  787. p6_ea_a6
  788.     :    io_short_addr    /* must be forced to tell from abs_addr */
  789.             {if($1 != -1) {
  790.                 w0 |= ($1 & 0x3F) << 8 | 0x008000;
  791.                 if($1 < 0xFFC0 && pass == 2)
  792.                     yyerror("warning: address operand truncated");
  793.             }}
  794.     |    abs_short_addr    /* must be forced to tell from abs_addr */
  795.             {if($1 != -1) {
  796.                 w0 |= ($1 & 0x3F) << 8 | 0x000000;
  797.                 if($1 > 0x003F && pass == 2)
  798.                     yyerror("warning: address operand truncated");
  799.             }}
  800.     |    ea    /* can use abs_addr */
  801.             {w0 |= 0x004000;}
  802.     ;
  803.  
  804. /*%%%************************** move instructions **********************/
  805.  
  806. move_inst
  807.     :    OP_MOVEP movep_args
  808.     |    OP_MOVEM movem_args
  809.     |    OP_MOVEC movec_args
  810.     |    OP_LUA ea_short regs
  811.             {w0 |= 0x044010 | $2 << 8 | $3.r4;}
  812.     |    OP_TCC tcc_args
  813.             {w0 |= $1 << 12;}
  814.     ;           
  815.  
  816. tcc_args
  817.     :    tcc_sd
  818.             {w0 |= 0x020000 | $1 << 3;}
  819.     |    tcc_sd RREG ',' RREG
  820.             {w0 |= 0x030000 | $1 << 3 | $2 << 8 | $4;}
  821.     ;
  822.  
  823. tcc_sd    :    regs /* a_b */ ',' regs /* a_b */
  824.             {if($1.flags & R_AB && $3.flags & R_AB) {
  825.                 if($1.ab == $3.ab) 
  826.                     yyerror("source and dest must be different");
  827.                 $$ = $3.ab;
  828.             } else if($1.flags & R_XREG && $3.flags & R_AB) {
  829.                 $$ = 0x8 | $1.xreg << 2 | $3.ab;
  830.             } else if($1.flags & R_YREG && $3.flags & R_AB) {
  831.                 $$ = 0xA | $1.yreg << 2 | $3.ab;
  832.             } else 
  833.                 yyerror("illegal TCC operands");
  834.             }
  835.     ;
  836.  
  837. sd3    :    regs /* XREG */ ',' regs /* a_b */
  838.             {if($1.flags & R_XREG && $3.flags & R_AB) {
  839.                 $$ = $1.xreg << 2 | $3.ab;
  840.             } else if($1.flags & R_YREG && $3.flags & R_AB) {
  841.                 $$ = $1.yreg << 2 | $3.ab;
  842.             }}
  843.     ;
  844.  
  845. movec_args
  846.     :    x_or_y ea ',' regs /* ctl_reg */
  847.             {if($1 == 0) {
  848.                 w0 |= 0x05C020 | $4.ctl_reg;
  849.             } else {
  850.                 w0 |= 0x05C060 | $4.ctl_reg;
  851.             }}
  852.     |    regs /* ctl_reg */ ',' x_or_y ea
  853.             {if($3 == 0) {
  854.                 w0 |= 0x054020 | $1.ctl_reg;
  855.             } else {
  856.                 w0 |= 0x054060 | $1.ctl_reg;
  857.             }}
  858.     |    ix ',' regs /* ctl_reg */
  859.             {if($1 < 256) {
  860.                 w0 |= 0x0500A0 | ($1 & 0xFF) << 8 | $3.ctl_reg; 
  861.             } else {
  862.                 w0 |= 0x05C020 | 0x003400 | $3.ctl_reg;
  863.                 uses_w1++; w1 = $1 & 0xFFFF;
  864.             }}
  865.     |    x_or_y abs_short_addr ',' regs /* ctl_reg */
  866.             {if($1 == 0) {
  867.                 w0 |= 0x058020 | ($2 & 0x3F) << 8 | $4.ctl_reg;
  868.             } else {
  869.                 w0 |= 0x058060 | ($2 & 0x3F) << 8 | $4.ctl_reg;
  870.             }
  871.             if($2 > 0x003F && pass == 2)
  872.                 yyerror("warning: address operand truncated");
  873.             }
  874.     |    regs /* ctl_reg */ ',' x_or_y abs_short_addr
  875.             {if($3 == 0) {
  876.                 w0 |= 0x050020 | ($4 & 0x3F) << 8 | $1.ctl_reg;
  877.             } else {
  878.                 w0 |= 0x050060 | ($4 & 0x3F) << 8 | $1.ctl_reg;
  879.             }
  880.             if($4 > 0x003F && pass == 2)
  881.                 yyerror("warning: address operand truncated");
  882.             }
  883.     |    regs /* ctl_reg */ ',' regs
  884.             {if($1.flags & R_CTL_REG) {
  885.                 w0 |= 0x0440A0 | $3.r6 << 8 | $1.ctl_reg;
  886.             } else if($3.flags & R_CTL_REG) {
  887.                 w0 |= 0x04C0A0 | $1.r6 << 8 | $3.ctl_reg;
  888.             } else if($1.flags & $3.flags & R_CTL_REG) {
  889.                 /* bogus? $$$ */
  890.                        w0 |= 0x04C0A0 | ($1.ctl_reg | 0x20) << 8 | 
  891.                 $3.ctl_reg;
  892.             } else {
  893.                 yyerror("MOVEC must reference a control reg");
  894.             }}
  895.     ;
  896.  
  897. movep_args
  898.     :    x_or_y movep_ea_pp ',' x_or_y movep_ea_pp
  899.             {w0 |= 0x084080;
  900.             switch($2.pp << 1 | $5.pp) {
  901.                 case 0:    case 3:
  902.                     yyerror("illegal MOVEP; can't move EA to EA or IO to IO");
  903.                     break;
  904.                 case 1:    /* ea, pp */
  905.                     w0 |= $4 << 16 | 1 << 15 | $1 << 6 |
  906.                         ($5.ext & 0x3F);
  907.                     if($2.mode == 0x003000) {
  908.                         w0 |= 0x003000;
  909.                         uses_w1++;
  910.                         w1 = $2.ext;
  911.                     } else {
  912.                         w0 |= $2.mode;
  913.                     }
  914.                     break;
  915.                 case 2:    /* pp, ea */
  916.                     w0 |= $1 << 16 | 0 << 15 | $4 << 6 |
  917.                         ($2.ext & 0x3F);
  918.                     if($5.mode == 0x003000) {
  919.                         w0 |= 0x003000;
  920.                         uses_w1++;
  921.                         w1 = $5.ext;
  922.                     } else {
  923.                         w0 |= $5.mode;
  924.                     }
  925.                     break;
  926.             }}
  927.     |    ix ',' x_or_y num_or_sym
  928.             {w0 |= 0x084080;
  929.             w0 |= $3 << 16 | 1 << 15 | 0x34 << 8 | ($4 & 0x3F);
  930.             uses_w1++;
  931.             w1 = $1;}
  932.     |    PMEM ea ',' x_or_y num_or_sym
  933.             {w0 |= 0x084040;
  934.             w0 |= $4 << 16 | 1 << 15 | ($5 & 0x3F);}
  935.     |    x_or_y movep_ea_pp ',' PMEM ea
  936.             {w0 |= 0x084040;
  937.             if($2.mode != 0x003000 && $2.mode != 0)
  938.                 yyerror("illegal MOVEP");
  939.             w0 |= $1 << 16 | 0 << 15 | ($2.ext & 0x3F);}
  940.     |    regs ',' x_or_y num_or_sym
  941.             {w0 |= 0x084000;
  942.             w0 |= $3 << 16 | 1 << 15 | $1.r6 << 8 | ($4 & 0x3F);}
  943.     |    x_or_y movep_ea_pp ',' regs
  944.             {w0 |= 0x084000;
  945.             if(!$2.pp)
  946.                 yyerror("illegal MOVEP");
  947.             w0 |= $1 << 16 | 0 << 15 | $4.r6 << 8 | ($2.ext & 0x3F);}
  948.     ;
  949.  
  950. movep_ea_pp
  951.     :    abs_addr
  952.             {if($1 != -1 && $1 >= 0xFFC0) {
  953.                 /* defined symbol or constant, in i/o range */
  954.                 $$.pp = 1;
  955.                 $$.mode = 0;
  956.             } else {
  957.                 /* either out of i/o range or symbol not */
  958.                 /* yet defined:  assume ea extension */
  959.                 $$.pp = 0;
  960.                 $$.mode = 0x003000;
  961.             }
  962.             $$.ext = $1;}
  963.     |    io_short_addr    /* forced i/o short */
  964.             {$$.pp = 1;
  965.             $$.mode = 0;
  966.             if($1 < 0xFFC0 && pass == 2)
  967.                 yyerror("warning: address operand truncated");
  968.             $$.ext = $1;}
  969.     |    ea_no_ext
  970.             {$$.mode = $1 << 8;
  971.             $$.ext = $1;}
  972.     ;
  973.  
  974. movem_args
  975.     :    regs ',' PMEM ea_a6
  976.             {w0 |= 0x070000 | 0 << 15 | $1.r6;}
  977.     |    PMEM ea_a6 ',' regs
  978.             {w0 |= 0x070000 | 1 << 15 | $4.r6;}
  979.     ;
  980.  
  981. /*%%%**************** memory reference fields ************************/
  982.  
  983. b5_10111_max
  984.     :    ix
  985.             {$$ = $1; if($1 > 0x17) yyerror("illegal bit number");}
  986.     ;
  987.  
  988. x_or_y    :    XMEM
  989.             {$$ = 0;}
  990.     |    YMEM
  991.             {$$ = 1;}
  992.     ;
  993.  
  994. /*%%%**************** effective address fields ************************/
  995.  
  996. ea_a6    :    ea
  997.             {w0 |= 0x004080;}
  998.     |    abs_short_addr
  999.             {w0 |= ($1 & 0x3F) << 8;
  1000.             if($1 > 0x003F && pass == 2)
  1001.                 yyerror("warning: address operand truncated");
  1002.             }
  1003.     ;
  1004.  
  1005. ea_a12    :    ea
  1006.             {$$ = 1;}
  1007.     |    abs_short_addr
  1008.             {w0 |= $1 & 0xFFF; $$ = 0;
  1009.             if($1 > 0x0FFF && pass == 2)
  1010.                 yyerror("warning: address operand truncated");
  1011.             }
  1012.     ;
  1013.  
  1014. ea    :    abs_addr
  1015.             {w0 |= 0x003000;
  1016.             uses_w1++;
  1017.             w1 |= $1;
  1018.             $$ = 0x003000;}
  1019.     |    ea_no_ext
  1020.             {w0 |= $1 << 8;
  1021.             $$ = $1 << 8;}
  1022.     ;
  1023.  
  1024. ea_no_ext
  1025.     :    ea_short
  1026.             {$$ = $1;}
  1027.     |    '(' RREG ')'
  1028.             {$$ = 4 << 3 | $2;}
  1029.     |    '(' RREG '+' NREG ')'
  1030.             {$$ = 5 << 3 | $2;
  1031.             if($2 != $4) yyerror("Rn and Nn must be same number");}
  1032.     |    '-' '(' RREG ')'
  1033.             {$$ = 7 << 3 | $3;}
  1034.     ;
  1035.  
  1036. ea_short
  1037.     :    '(' RREG ')' '-' NREG
  1038.             {$$ = 0 << 3 | $2;
  1039.             if($2 != $5) yyerror("Rn and Nn must be same number");}
  1040.     |    '(' RREG ')' '+' NREG
  1041.             {$$ = 1 << 3 | $2;
  1042.             if($2 != $5) yyerror("Rn and Nn must be same number");}
  1043.     |    '(' RREG ')' '-'
  1044.             {$$ = 2 << 3 | $2;}
  1045.     |    '(' RREG ')' '+'
  1046.             {$$ = 3 << 3 | $2;}
  1047.     ;
  1048.  
  1049. /*%%%******************* register fields ******************************/
  1050.  
  1051. regs    :    XREG
  1052.             {$$.r6 = $$.r5 = 0x04 | $1;
  1053.             $$.sdx = $1;
  1054.             $$.xreg = $1;
  1055.             $$.flags = R_R6|R_R5|R_XREG|R_SDX;}
  1056.     |    YREG
  1057.             {$$.r6 = $$.r5 = 0x06 | $1;
  1058.             $$.sdy = $1;
  1059.             $$.yreg = $1;
  1060.             $$.flags = R_R6|R_R5|R_SDY|R_YREG;}
  1061.     |    AREG
  1062.             {switch($1) {
  1063.                 case 0: 
  1064.                     $$.r6 = $$.r5 = 0x08 | 0; 
  1065.                     break;
  1066.                 case 1: 
  1067.                     $$.r6 = $$.r5 = 0x08 | 4; 
  1068.                     break;
  1069.                 case 2: 
  1070.                     $$.r6 = $$.r5 = 0x08 | 2; 
  1071.                     break;
  1072.             }
  1073.             $$.flags = R_R6|R_R5;}
  1074.     |    BREG
  1075.             {switch($1) {
  1076.                 case 0: 
  1077.                     $$.r6 = $$.r5 = 0x08 | 1; break;
  1078.                 case 1: 
  1079.                     $$.r6 = $$.r5 = 0x08 | 5; break;
  1080.                 case 2: 
  1081.                     $$.r6 = $$.r5 = 0x08 | 3; break;
  1082.             }
  1083.             $$.flags = R_R6|R_R5;}
  1084.     |    AAAA
  1085.             {$$.r6 = $$.r5 = 0x0E;
  1086.             $$.sdx = $$.sdy = 0x2;
  1087.             $$.ab = 0;
  1088.             $$.lsd = 4;
  1089.             $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD;}
  1090.     |    BBBB
  1091.             {$$.r6 = $$.r5 = 0x0F;
  1092.             $$.sdx = $$.sdy = 0x3;
  1093.             $$.ab = 1;
  1094.             $$.lsd = 5;
  1095.             $$.flags = R_R6|R_R5|R_SDX|R_SDY|R_AB|R_LSD;}
  1096.     |    RREG
  1097.             {$$.r6 = $$.r5 = 0x10 | $1;
  1098.             $$.r4 = 0x00 | $1;
  1099.             $$.flags = R_R6|R_R5|R_R4;}
  1100.     |    NREG
  1101.             {$$.r6 = $$.r5 = 0x18 | $1;
  1102.             $$.r4 = 0x08 | $1;
  1103.             $$.flags = R_R6|R_R5|R_R4;}
  1104.     |    MREG
  1105.             {$$.r6 = 0x20 | $1;
  1106.             $$.r5 = -1;
  1107.             $$.ctl_reg = $1;
  1108.             $$.flags = R_R6|R_R5|R_CTL_REG;}
  1109.     |    prog_ctl_reg
  1110.             {$$.r6 = 0x38 | $1;
  1111.             $$.r5 = -1;
  1112.             $$.ctl_reg = 0x18 | $1;
  1113.             $$.flags = R_R6|R_R5|R_CTL_REG;}
  1114.     |    A10
  1115.             {$$.lsd  = 0;
  1116.             $$.flags = R_LSD;}
  1117.     |    B10
  1118.             {$$.lsd = 1;
  1119.             $$.flags = R_LSD;}
  1120.     |    XXXX
  1121.             {$$.lsd = 2;
  1122.             $$.flags = R_LSD;}
  1123.     |    YYYY
  1124.             {$$.lsd = 3;
  1125.             $$.flags = R_LSD;}
  1126.     |    AABB
  1127.             {$$.lsd = 6;
  1128.             $$.flags = R_LSD;}
  1129.     |    BBAA
  1130.             {$$.lsd = 7;
  1131.             $$.flags = R_LSD;}
  1132.     ;
  1133.  
  1134. prog_ctl_reg
  1135.     :    SR
  1136.             {$$ = 1;}
  1137.     |    OMR
  1138.             {$$ = 2;}
  1139.     |    SP
  1140.             {$$ = 3;}
  1141.     |    SSH
  1142.             {$$ = 4;}
  1143.     |    SSL
  1144.             {$$ = 5;}
  1145.     |    LA
  1146.             {$$ = 6;}
  1147.     |    LC
  1148.             {$$ = 7;}
  1149.     ;
  1150.  
  1151. funky_ctl_reg
  1152.     :    MR
  1153.             {$$ = 0;}
  1154.     |    CCR
  1155.             {$$ = 1;}
  1156.     |    OMR
  1157.             {$$ = 2;}
  1158.     ;
  1159.  
  1160. /*%%%************************* parallel moves *************/
  1161.  
  1162. parallel_move
  1163.     :    i_move
  1164.     |    u_move
  1165.     |    x_or_y_move
  1166.     |    xr_move
  1167.     |    ry_move
  1168.     |    r_move
  1169.     |    xy_move
  1170.     |    l_move
  1171.     ;
  1172.  
  1173. i_move  :    ix ',' regs
  1174.             {if($1 <= 0xFF) {
  1175.                 w0 |= 0x200000 | ($1 & 0xFF) << 8 | 
  1176.                     $3.r5 << 16;
  1177.             } else { /* go long, use X: format */
  1178.                 w0 |= 0x400000 | 0x00F400 | 
  1179.                     ($3.r5 >> 3 & 3) << 20 | 
  1180.                     ($3.r5 & 7) << 16;
  1181.                 uses_w1++; w1 = $1;
  1182.             }}
  1183.     ;
  1184.  
  1185. r_move    :    regs ',' regs
  1186.             {
  1187.                 if($1.flags & R_R5 & $3.flags) 
  1188.                     w0 |= 0x200000 | $3.r5 << 8 | $1.r5 << 13;
  1189.                 else
  1190.                     yyerror("illegal R move");
  1191.             }    
  1192.     ;
  1193.  
  1194. u_move    :    ea_short
  1195.             {w0 |= 0x204000 | $1 << 8;}
  1196.     ;
  1197.  
  1198. x_or_y_move
  1199.     :    x_or_y ea ',' regs
  1200.             {w0 |= 0x40C000 | $1 << 19;
  1201.             w0 |= ($4.r5 >> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
  1202.     |    x_or_y abs_short_addr ',' regs
  1203.             {w0 |= 0x408000 | $1 << 19 | ($2 & 0x3F) << 8;
  1204.             if($2 > 0x003F && pass == 2)
  1205.                 yyerror("warning: address operand truncated");
  1206.             w0 |= ($4.r5>> 3 & 3) << 20 | ($4.r5 & 7) << 16;}
  1207.     |    regs ',' x_or_y ea
  1208.             {w0 |= 0x404000 | $3 << 19;
  1209.             w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
  1210.     |    regs ',' x_or_y abs_short_addr
  1211.             {w0 |= 0x400000 | $3 << 19 | ($4 & 0x3F) << 8;
  1212.             if($4 > 0x003F && pass == 2)
  1213.                 yyerror("warning: address operand truncated");
  1214.             w0 |= ($1.r5 >> 3 & 3) << 20 | ($1.r5 & 7) << 16;}
  1215.     |    ix_long ',' regs
  1216.             {w0 |= 0x400000 | 0x00F400 | ($3.r5 >> 3 & 3) << 20 |
  1217.                 ($3.r5 & 7) << 16;
  1218.             uses_w1++; w1 = $1;
  1219.             }
  1220.     ;
  1221.  
  1222. xr_move    :    x_or_y /* XMEM */ ea ',' regs    regs /* a_b */ ',' YREG
  1223.             {if($1 == 0 && $5.flags & R_AB) {
  1224.                 w0 |= 0x108000 | $4.sdx << 18 | $5.ab << 17 |
  1225.                     $7 << 16;
  1226.             } else {
  1227.                 yyerror("illegal X:R move");
  1228.             }}
  1229.     |     ix ',' regs        regs /* a_b */ ',' YREG
  1230.             {if($4.flags & R_AB) {
  1231.                 w0 |= 0x10B400 | $3.sdx << 18 | $4.ab << 17 |
  1232.                     $6 << 16;
  1233.                 uses_w1++;
  1234.                 w1 |= $1 & 0xFFFFFF;
  1235.             } else {
  1236.                 yyerror("illegal X:R move");
  1237.             }}
  1238.     |    regs ',' x_or_y /* XMEM */ ea    regs /* a_b */ ',' regs/*YREG*/
  1239.             {if($1.flags & R_SDX && $3 == 0 && $5.flags & R_AB &&
  1240.                 $7.flags & R_YREG) {
  1241.                 w0 |= 0x100000 | $1.sdx << 18 | $5.ab << 17 |
  1242.                     $7.yreg << 16;
  1243.             } else if($1.flags & R_AB && $3 == 0 && 
  1244.                 $5.flags & R_XREG && $7.flags & R_AB) {
  1245.                 if($5.xreg != 0) yyerror("must use X0");
  1246.                 if($1.ab == 0 && $7.ab == 0)
  1247.                     w0 |= 0x080000;
  1248.                 else if($1.ab == 1 && $7.ab == 1)
  1249.                     w0 |= 0x090000;
  1250.                 else
  1251.                     yyerror("illegal X:R move");
  1252.             } else {
  1253.                 yyerror("illegal X:R move");
  1254.             }}
  1255.     ;
  1256.  
  1257. ry_move    :    regs /* a_b */ ',' regs /* XREG    */      YMEM ea ',' regs
  1258.             {if($3.flags & R_XREG && $7.flags & (R_YREG|R_AB)) {
  1259.                 w0 |= 0x10C000 | $1.ab << 19 | $3.yreg << 18 |
  1260.                     $7.sdy << 16;
  1261.             } else {
  1262.                 yyerror("illegal R:Y move");
  1263.             }}
  1264.     |    regs /* a_b */ ',' regs /* XREG    */    ix ',' regs
  1265.             {if($3.flags & R_XREG && $6.flags & (R_YREG|R_AB)) {
  1266.                 w0 |= 0x10F400 | $1.ab << 19 | $3.xreg << 18 |
  1267.                     $6.sdy << 16;
  1268.                 uses_w1++;
  1269.                 w1 |= $4 & 0xFFFFFF;
  1270.             } else {
  1271.                 yyerror("illegal R:Y move");
  1272.             }}
  1273.     |    regs /* a_b */ ',' regs /* XREG    */    regs ',' YMEM ea
  1274.             {if($1.flags & R_AB && $3.flags & R_XREG) {
  1275.                 w0 |= 0x104000 | $1.ab << 19 | $3.xreg << 18 |
  1276.                 $4.sdy << 16;
  1277.             } else if ($1.flags & R_YREG && $3.flags & R_AB &&
  1278.                 $4.flags & R_AB) {
  1279.                 if($1.yreg != 0) yyerror("must use Y0");
  1280.                 if($3.ab == 0 && $4.ab == 0)
  1281.                     w0 |= 0x088000;
  1282.                 else if($3.ab == 1 && $4.ab == 1)
  1283.                     w0 |= 0x098000;
  1284.                 else
  1285.                     yyerror("illegal R:Y move");
  1286.             } else {
  1287.                 yyerror("illegal R:Y move");
  1288.             }}
  1289.     ;
  1290.  
  1291. l_move    :    LMEM ea ',' regs /* lsd */
  1292.             {w0 |= 0x40C000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;}
  1293.     |    regs /* lsd */ ',' LMEM ea
  1294.             {w0 |= 0x404000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;}
  1295.     |    LMEM abs_short_addr ',' regs /* lsd */
  1296.             {w0 |= 0x408000 | ($4.lsd & 3) << 16 | ($4.lsd >> 2) << 19;
  1297.             if($2 > 0x003F && pass == 2)
  1298.                 yyerror("warning: address operand truncated");
  1299.             w0 |= ($2 & 0x3F) << 8;}
  1300.     |    regs /* lsd */ ',' LMEM abs_short_addr
  1301.             {w0 |= 0x400000 | ($1.lsd & 3) << 16 | ($1.lsd >> 2) << 19;
  1302.             if($4 > 0x003F && pass == 2)
  1303.                 yyerror("warning: address operand truncated");
  1304.             w0 |= ($4 & 0x3F) << 8;}
  1305.     ;
  1306.  
  1307. xy_move    :    x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs    YMEM ea /*ea_strange*/ ',' regs
  1308.             /* $$$ where is $4 and $8 (sdy) used? */
  1309.             {int eax = $2, eay = $6;
  1310.             w0 = 0xC08000;    /* both write */
  1311.                   if(eax & 0x4 == eay & 0x4)
  1312.                 yyerror("registers must be in opposite halves");
  1313.             w0 |= eax << 8 | (eay & 3) << 13 | (eay >> 3) << 18;}
  1314.     |    x_or_y /*XMEM*/ ea /*ea_strange*/ ',' regs    regs ',' YMEM ea /*ea_strange*/
  1315.             {int eax = $2, eay = $8;
  1316.             w0 = 0x808000;    /* X:write, Y:read */
  1317.                   if(eax & 0x4 == eay & 0x4)
  1318.                 yyerror("registers must be in opposite halves");
  1319.             w0 |= eax << 8 | (eay & 3) << 13 | (eay >> 3) << 18;}
  1320.     |    regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/    YMEM ea /*ea_strange*/ ',' regs
  1321.             {int eax = $4, eay = $6;
  1322.                   w0 = 0xC00000;    /* X:read, Y:write */
  1323.             if(eax & 0x4 == eay & 0x4)
  1324.                 yyerror("registers must be in opposite halves");
  1325.             w0 |= eax << 8 | (eay & 3) << 13 | (eay >> 3) << 18;}
  1326.     |    regs ',' x_or_y /*XMEM*/ ea /*ea_strange*/    regs ',' YMEM ea /*ea_strange*/
  1327.             {int eax = $4, eay = $8;
  1328.                   w0 = 0x800000;    /* both read */
  1329.             if(eax & 0x4 == eay & 0x4)
  1330.                 yyerror("registers must be in opposite halves");
  1331.             w0 |= eax << 8 | (eay & 3) << 13 | (eay >> 3) << 18;}
  1332.     ;
  1333.  
  1334. /*%%%******* absolute address and immediate data fields ************/
  1335.  
  1336. num    :    CHEX
  1337.             {$$ = $1;}
  1338.     |    CDEC
  1339.             {$$ = $1;}
  1340.     |    FRAC
  1341.             {$$ = $1;}
  1342.     ;
  1343.  
  1344. ix    :    '#' expr
  1345.             {$$ = $2;}
  1346.     |    '#' '<' expr
  1347.             {$$ = $3 & 0xFF;}
  1348.     ;
  1349.  
  1350. ix_long    :    '#' '>' expr
  1351.             {$$ = $3;}
  1352.     ;
  1353.  
  1354. abs_addr
  1355.     :    expr
  1356.             {$$ = $1;}
  1357.     |    '*'
  1358.             {$$ = pc;}
  1359.     ;
  1360.  
  1361. abs_short_addr
  1362.     :    '<' expr
  1363.             {$$ = $2;}
  1364.     |    '<' '*'
  1365.             {$$ = pc;}
  1366.     ;
  1367.  
  1368. io_short_addr
  1369.     :    SHL expr
  1370.             {$$ = $2;} 
  1371.     ;
  1372.  
  1373. num_or_sym
  1374.     :    num
  1375.             {$$ = $1 & 0xFFFFFF;}
  1376.     |    SYM
  1377.             {$$ = sym_ref($1); free($1);}
  1378.     ;
  1379.  
  1380. num_or_sym_expr
  1381.     :    num
  1382.             {$$ = $1;}
  1383.     |    SYM
  1384.             {$$ = sym_ref($1); free($1);}
  1385.     |    CHAR
  1386.             {$$ = $1;}
  1387.     ;
  1388.  
  1389. expr    :    expr '|' expr
  1390.             {$$ = $1 | $3;}
  1391.     |    expr '^' expr
  1392.             {$$ = $1 ^ $3;}
  1393.     |    expr '&' expr
  1394.             {$$ = $1 & $3;}
  1395.     |    expr SHR expr
  1396.             {$$ = $1 >> $3;}
  1397.     |    expr SHL expr
  1398.             {$$ = $1 << $3;}
  1399.     |    expr '-' expr
  1400.             {$$ = $1 - $3;}
  1401.     |    expr '+' expr
  1402.             {$$ = $1 + $3;}
  1403.     |    expr '%' expr
  1404.             {$$ = $1 % $3;}
  1405.     |    expr '/' expr
  1406.             {$$ = $1 / $3;}
  1407.     |    expr '*' expr
  1408.             {$$ = $1 * $3;}
  1409.     |    '-' expr %prec '~'
  1410.             {$$ = - $2;}
  1411.     |    '~' expr
  1412.             {$$ = ~ $2;}
  1413.     |    '(' expr ')'
  1414.             {$$ = $2;}
  1415.     |    num_or_sym_expr
  1416.             {$$ = $1;}
  1417.     ;
  1418.  
  1419. /*%%%****************** end ******************************/
  1420.  
  1421. %%
  1422.  
  1423. #include <stdio.h>
  1424.  
  1425. int yydebug;
  1426.  
  1427. extern struct {int n; char *name;} tok_tab[];
  1428. extern int n_tok;
  1429.  
  1430. char *tok_print(tok)
  1431. int tok;
  1432. {
  1433.     int i;
  1434.     static char buf[32];
  1435.  
  1436.     if(tok < 256) {
  1437.     sprintf(buf, "'%c'", tok);
  1438.     return(buf);
  1439.     } else {
  1440.     for(i = 0; i < n_tok; i++) {
  1441.         if(tok == tok_tab[i].n)
  1442.         return(tok_tab[i].name);
  1443.     }
  1444.     }
  1445.     return("<unknown>");
  1446. }
  1447.  
  1448. yyerror(s)
  1449. char *s;
  1450. {
  1451.     extern int error;
  1452.     error++;
  1453.  
  1454.     if(pass == 2) {
  1455.     fprintf(stderr, "%s: line %d: %s (tok=%s)\n", curfile, curline,
  1456.         s, tok_print(yychar));
  1457.     fprintf(stderr, "%s\n", inline); 
  1458.     printf("%s: line %d: %s (tok=%s)\n", curfile, curline,
  1459.         s, tok_print(yychar));
  1460.     printf("%s\n", inline); 
  1461.     }
  1462. }
  1463.  
  1464. char *luntab(s)
  1465. char *s;
  1466. {
  1467.     static char buf[256];
  1468.  
  1469.     strcpy(buf, s);
  1470.  
  1471.     untab(buf);
  1472.     return(buf);
  1473. }
  1474.